package org.ligson.httptest.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

@Slf4j
public class HttpUtil {
    public static RequestConfig getRequestConfig() {
        int timeout = 120000;
        return RequestConfig.custom()
                .setConnectTimeout(timeout)
                .setSocketTimeout(timeout).build();
    }

    public static CloseableHttpClient getHttpClient() {
        return HttpClientBuilder.create().build();
    }

    public static String doGet(String url) {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(getRequestConfig());
        return doRequest(httpGet, null);
    }

    public static String doGet(String url, Map<String, String> headers) {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(getRequestConfig());
        return doRequest(httpGet, headers);
    }

    public static String doPostJson(String url, Map<String, String> headers, String jsonBody) {
        HttpPost httpPost = new HttpPost(url);
        StringEntity stringEntity = new StringEntity(jsonBody, "UTF-8");
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put("Content-Type", "application/json;charset=UTF-8");
        httpPost.setEntity(stringEntity);
        httpPost.setConfig(getRequestConfig());
        return doRequest(httpPost, headers);
    }

    public static String doPostForm(String url, Map<String, String> headers, Map<String, String> params) {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> pairs = new ArrayList<>();
        if (params != null) {
            params.forEach((k, v) -> {
                pairs.add(new BasicNameValuePair(k, v));
            });
        }
        UrlEncodedFormEntity formEntity = null;
        try {
            formEntity = new UrlEncodedFormEntity(pairs, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
        httpPost.setEntity(formEntity);
        httpPost.setConfig(getRequestConfig());
        return doRequest(httpPost, headers);
    }

    public static String doRequest(HttpUriRequest request, Map<String, String> headers) {
        String url = request.getRequestLine().getUri();
        if (headers != null) {
            headers.forEach(request::setHeader);
        }

        CloseableHttpResponse response;
        long startTime = new Date().getTime();
        try {
            log.error("准备请求URL:{}", request.getURI());
            response = getHttpClient().execute(request);
            long endTime = new Date().getTime();
            log.debug("准备请求URL:{}正常，耗时:{}s", request.getURI(), (endTime - startTime) / 1000.0);
        } catch (IOException e) {
            log.error("http:{} execute error:{}", url, e.getMessage(), e);
            return null;
        }
        int code = response.getStatusLine().getStatusCode();
        log.debug("http:{} response code :{}", url, code);
        String entity = null;
        try {
            entity = EntityUtils.toString(response.getEntity(), "UTF-8");
            log.debug("http:{} response content :{}", url, entity);
        } catch (IOException e) {
            log.error("http:{} response read stream error:{}", url, e.getMessage(), e);
        }
        if (HttpStatus.SC_OK == code) {
            return entity;
        } else {
            return null;
        }
    }
}
